using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;

using SBPweb.Controls.Windows;
using SBPweb.Themes.Windows;
using SBPweb.Themes.Windows.Skins;

namespace SBPweb.Controls.Windows.Editors
{
	/// <summary>
	/// Class of ProgressBar
	/// </summary>
	[ToolboxBitmap(typeof(System.Windows.Forms.ProgressBar))]
	public partial class ProgressBar : System.Windows.Forms.ProgressBar, ISkinnable
	{
		#region Private members

		private bool mUseDefaultSkin = true;

		private Margin mSizingMargin;
		private Margin mContentMargin;

		private Margin mCSizingMargin;
		private SBPweb.Themes.Windows.Skins.Size mMinSize;

		private Skin mSkin;

		//private MouseEventState mMState = MouseEventState.None;

		private float percentageValue;

		private bool tiled = false;
		private bool stretched = false;

		#endregion

		#region Constructor logic

		public ProgressBar()
		{
			InitializeComponent();


			InitializeMargins();
			InitializeMinSize();

			SetStyle();
			RegisterEventHandlers();
		}

		public ProgressBar(Skin skin)
		{
			mSkin = skin;

			InitializeComponent();

			InitializeMargins();
			InitializeMinSize();

			SetStyle();
			RegisterEventHandlers();
		}

		private void SetStyle()
		{
			this.SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);
		}

		private void RegisterEventHandlers()
		{
			DefaultLookAndFeel.OnSkinChanged += new EventHandler(DefaultLookAndFeel_OnSkinChanged);
		}


		#endregion

		#region Custom draw

		/*const int WM_PAINT = 0x000F;

		protected override void WndProc(ref Message m)
		{
			base.WndProc(ref m);

			if (m.Msg == WM_PAINT)
			{
				InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.ClientRectangle));
			}
		}*/

		protected override void OnPaint(PaintEventArgs e)
		{
			if (Skin == null && (!UseDefaultSkin || DefaultLookAndFeel.Skin == null))
			{
				base.OnPaint(e);
				return;
			}

			OnPaintBackground(e);

			System.Drawing.Image img = Skin.GetImageFromBitmapResource(Skin.KeyPrefix + "editors.progressborder.png");

			int imgCount = 1;
			int imgWidth = img.Width ;
			int imgHeight = (Int32)(img.Height / imgCount);
			int imgTop;
			int imgLeft;

			imgWidth = (Int32)(img.Width / imgCount);
			imgHeight = img.Height;
			imgTop = 0;
			imgLeft = 0;

			#region Image parts
			Rectangle iLT = new Rectangle(imgLeft, imgTop, mSizingMargin.Left, mSizingMargin.Top);
			Rectangle iT = new Rectangle(imgLeft + mSizingMargin.Left, imgTop, imgWidth - mSizingMargin.Horizontal, mSizingMargin.Top);
			Rectangle iRT = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop, mSizingMargin.Right, mSizingMargin.Top);
			Rectangle iLM = new Rectangle(imgLeft, imgTop + mSizingMargin.Top, mSizingMargin.Left, imgHeight - mSizingMargin.Vertical);
			Rectangle iM = new Rectangle(imgLeft + mSizingMargin.Left, imgTop + mSizingMargin.Top, imgWidth - mSizingMargin.Horizontal, imgHeight - mSizingMargin.Vertical);
			Rectangle iRM = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop + mSizingMargin.Top, mSizingMargin.Right, imgHeight - mSizingMargin.Vertical);
			Rectangle iLB = new Rectangle(imgLeft, imgTop + imgHeight - mSizingMargin.Bottom, mSizingMargin.Left, mSizingMargin.Bottom);
			Rectangle iB = new Rectangle(imgLeft + mSizingMargin.Left, imgTop + imgHeight - mSizingMargin.Bottom, imgWidth - mSizingMargin.Horizontal, mSizingMargin.Bottom);
			Rectangle iRB = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop + imgHeight - mSizingMargin.Bottom, mSizingMargin.Right, mSizingMargin.Bottom);
			#endregion

			#region Window parts
			Rectangle tLT = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Top, mSizingMargin.Left, mSizingMargin.Top);
			Rectangle tT = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Top, this.ClientRectangle.Width - mSizingMargin.Horizontal, mSizingMargin.Top);
			Rectangle tRT = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Top, mSizingMargin.Right, mSizingMargin.Top);
			Rectangle tLM = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Top + mSizingMargin.Top, mSizingMargin.Left, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tM = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Top + mSizingMargin.Top, this.ClientRectangle.Width - mSizingMargin.Horizontal, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tRM = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Top + mSizingMargin.Top, mSizingMargin.Right, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tLB = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Bottom - mSizingMargin.Bottom, mSizingMargin.Left, mSizingMargin.Bottom);
			Rectangle tB = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Bottom - mSizingMargin.Bottom, this.ClientRectangle.Width - mSizingMargin.Horizontal, mSizingMargin.Bottom);
			Rectangle tRB = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Bottom - mSizingMargin.Bottom, mSizingMargin.Right, mSizingMargin.Bottom);
			#endregion

			#region Drawing
			e.Graphics.DrawImage(img, tLT, iLT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tT, iT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRT, iRT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tLM, iLM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tM, iM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRM, iRM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tLB, iLB, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tB, iB, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRB, iRB, GraphicsUnit.Pixel);

			DrawChunk(e, mSizingMargin.Left, mSizingMargin.Top, this.ClientSize.Width, this.ClientSize.Height);
			#endregion
		}

		private void InitializeMargins()
		{
			if (Skin == null)
			{
				mSizingMargin = new Margin();
				mCSizingMargin = new Margin();
				mContentMargin = new Margin();
			}
			else
			{
				if (Skin.SelectSingleNode("Elements/ProgressBorder/Image/SizingMargins") != null)
				{
					mSizingMargin = new Margin(Skin.SelectSingleNode("Elements/ProgressBorder/Image/SizingMargins"));
				}
				else
				{
					mSizingMargin = new Margin(new Padding(0));
				}

				if (Skin.SelectSingleNode("Elements/ProgressChunk/Image/SizingMargins") != null)
				{
					mCSizingMargin = new Margin(Skin.SelectSingleNode("Elements/ProgressChunk/Image/SizingMargins"));
				}
				else
				{
					mCSizingMargin = new Margin(new Padding(0));
				}

				mContentMargin = new Margin(Skin.SelectSingleNode("Elements/ProgressBorder/ContentMargins"));
			}
		}

		private void InitializeMinSize()
		{
			if (Skin == null)
			{
				mMinSize = new SBPweb.Themes.Windows.Skins.Size();
			}
			else
			{
				mMinSize = new SBPweb.Themes.Windows.Skins.Size(Skin.SelectSingleNode("Elements/ProgressChunk/Size"));
			}
		}

		protected override void OnPaintBackground(PaintEventArgs e)
		{
			base.OnPaintBackground(e);
		}

		private void DrawChunk(PaintEventArgs e, int marginLeft, int marginTop, int width, int height)
		{

			System.Drawing.Image img = Skin.GetImageFromBitmapResource(Skin.KeyPrefix + "editors.progresschunk.png");

			tiled = false;
			stretched = false;
			
			if (Skin.SelectSingleNode("Elements/ProgressChunk/Image").Attributes["Stretch"] != null)
			{
				
				switch (Skin.SelectSingleNode("Elements/ProgressChunk/Image").Attributes["Stretch"].Value.ToLower() )
				{ 
					case "tile":
						tiled = true;
						break;
					case "stretch":
						stretched = true;
						break;
				}
			}

			if (tiled)
			{

				Rectangle src = new Rectangle(0, 0, img.Width, img.Height);

				if (this.Value > 0)
				{
					Rectangle dest = new Rectangle(3, 3, img.Width, height - 6); // let be progressBorder's width 3

					int nMax = (width - (2 * marginLeft)) / img.Width;

					percentageValue = (this.Value - this.Minimum) / (float)(this.Maximum - this.Minimum);

					int n = (int)Math.Round((nMax * percentageValue), MidpointRounding.AwayFromZero);

					for (int i = 0; i < n; i++, dest.X += dest.Width)
					{
						e.Graphics.DrawImage(img, dest, src, GraphicsUnit.Pixel);
					}
				}

			}

			if (stretched)
			{
				if (this.Value > 0)
				{
					int imgWidth = (img.Width != mCSizingMargin.Horizontal + 1)? img.Width - 1 : img.Width;
					int imgHeight = img.Height;
					int imgTop = 0;
					int imgLeft = 0;

					int chunkWidth = (int)((this.Value / (float)this.Maximum) * width);
					if (marginTop == 0)
					{
						marginTop = 3;
					}
					int chunkHeight = height - marginTop * 2;


					#region Image parts
					Rectangle iLT = new Rectangle(imgLeft, imgTop, mCSizingMargin.Left, mCSizingMargin.Top);
					Rectangle iT = new Rectangle(imgLeft + mCSizingMargin.Left, imgTop, imgWidth - mCSizingMargin.Horizontal, mCSizingMargin.Top);
					Rectangle iRT = new Rectangle(imgLeft + imgWidth - mCSizingMargin.Right, imgTop, mCSizingMargin.Right, mCSizingMargin.Top);
					Rectangle iLM = new Rectangle(imgLeft, imgTop + mCSizingMargin.Top, mCSizingMargin.Left, imgHeight - mCSizingMargin.Vertical);
					Rectangle iM = new Rectangle(imgLeft + mCSizingMargin.Left, imgTop + mCSizingMargin.Top, imgWidth - mCSizingMargin.Horizontal, imgHeight - mCSizingMargin.Vertical);
					Rectangle iRM = new Rectangle(imgLeft + imgWidth - mCSizingMargin.Right, imgTop + mCSizingMargin.Top, mCSizingMargin.Right, imgHeight - mCSizingMargin.Vertical);
					Rectangle iLB = new Rectangle(imgLeft, imgTop + imgHeight - mCSizingMargin.Bottom, mCSizingMargin.Left, mCSizingMargin.Bottom);
					Rectangle iB = new Rectangle(imgLeft + mCSizingMargin.Left, imgTop + imgHeight - mCSizingMargin.Bottom, imgWidth - mCSizingMargin.Horizontal, mCSizingMargin.Bottom);
					Rectangle iRB = new Rectangle(imgLeft + imgWidth - mCSizingMargin.Right, imgTop + imgHeight - mCSizingMargin.Bottom, mCSizingMargin.Right, mCSizingMargin.Bottom);
					#endregion

					#region Window parts
					Rectangle tLT = new Rectangle(marginLeft, marginTop, mCSizingMargin.Left, mCSizingMargin.Top);
					Rectangle tT = new Rectangle(marginLeft + mCSizingMargin.Left, marginTop, chunkWidth - mCSizingMargin.Horizontal, mCSizingMargin.Top);
					Rectangle tRT = new Rectangle(marginLeft + chunkWidth - mCSizingMargin.Right, marginTop, mCSizingMargin.Right, mCSizingMargin.Top);
					Rectangle tLM = new Rectangle(marginLeft, marginTop + mCSizingMargin.Top, mCSizingMargin.Left, chunkHeight - mCSizingMargin.Vertical);
					Rectangle tM = new Rectangle(marginLeft + mCSizingMargin.Left, marginTop + mCSizingMargin.Top, chunkWidth - mCSizingMargin.Horizontal, chunkHeight - mCSizingMargin.Vertical);
					Rectangle tRM = new Rectangle(marginLeft + chunkWidth - mCSizingMargin.Right, marginTop + mCSizingMargin.Top, mCSizingMargin.Right, chunkHeight - mCSizingMargin.Vertical);
					Rectangle tLB = new Rectangle(marginLeft, marginTop + chunkHeight - mCSizingMargin.Bottom, mCSizingMargin.Left, mCSizingMargin.Bottom);
					Rectangle tB = new Rectangle(marginLeft + mCSizingMargin.Left, marginTop + chunkHeight - mCSizingMargin.Bottom, chunkWidth - mCSizingMargin.Horizontal, mCSizingMargin.Bottom);
					Rectangle tRB = new Rectangle(marginLeft + chunkWidth - mCSizingMargin.Right, marginTop + chunkHeight - mCSizingMargin.Bottom, mCSizingMargin.Right, mCSizingMargin.Bottom);
					#endregion

					#region Drawing
					e.Graphics.DrawImage(img, tLT, iLT, GraphicsUnit.Pixel);
					e.Graphics.DrawImage(img, tT, iT, GraphicsUnit.Pixel);
					e.Graphics.DrawImage(img, tRT, iRT, GraphicsUnit.Pixel);
					e.Graphics.DrawImage(img, tLM, iLM, GraphicsUnit.Pixel);
					e.Graphics.DrawImage(img, tM, iM, GraphicsUnit.Pixel);
					e.Graphics.DrawImage(img, tRM, iRM, GraphicsUnit.Pixel);
					e.Graphics.DrawImage(img, tLB, iLB, GraphicsUnit.Pixel);
					e.Graphics.DrawImage(img, tB, iB, GraphicsUnit.Pixel);
					e.Graphics.DrawImage(img, tRB, iRB, GraphicsUnit.Pixel);

					#endregion
				}
			}
		}

		#endregion

		#region Events
		void this_MouseEnter(object sender, EventArgs e)
		{
			//mMState = MouseEventState.OnHover;
			this.Invalidate();
		}

		void this_MouseUp(object sender, MouseEventArgs e)
		{
			//if (e.X < 0 || e.X > this.Width || e.Y < 0 || e.Y > this.Height)
			//{
			//    mMState = MouseEventState.None;
			//}
			//else
			//{
			//    mMState = MouseEventState.OnHover;
			//}

			this.Invalidate();
		}

		void this_MouseDown(object sender, MouseEventArgs e)
		{
			//mMState = MouseEventState.OnDown;
			this.Invalidate();
		}

		void this_MouseLeave(object sender, EventArgs e)
		{
			//mMState = MouseEventState.None;
			this.Invalidate();
		}

		//void this_MouseHover(object sender, EventArgs e)
		//{
		//    //mMState = MouseEventState.OnHover;
		//}


		void DefaultLookAndFeel_OnSkinChanged(object sender, EventArgs e)
		{
			InitializeMargins();
			InitializeMinSize();
		}

		#endregion

		#region ISkinnable Members

		/// <summary>
		/// Use default skin?
		/// </summary>
		[Category("Look && feel")]
		public bool UseDefaultSkin
		{
			get
			{
				return mUseDefaultSkin;
			}
			set
			{
				mUseDefaultSkin = value;
				Invalidate();
			}
		}

		/// <summary>
		/// Used skin
		/// </summary>
		[Category("Look && feel")]
		public Skin Skin
		{
			get
			{
				if (this.UseDefaultSkin)
				{
					return DefaultLookAndFeel.Skin;
				}
				else
				{
					return mSkin;
				}
			}
			set
			{
				mSkin = value;
				Invalidate();
			}
		}

		#endregion
	}
}
